#include "UserManager.hpp"
#include "BusinessTask.hpp"
#include "MySQLClient.hpp"
#include "logger.h"
using std::cout;
using std::endl;
namespace wd{


UserLoginSection1::UserLoginSection1(wd::Packet & packet, wd::TcpConnectionptr tcpconn)
    :_packet(packet)
     ,_tcpconn(tcpconn){

     }

void UserLoginSection1::process(){
    /* printf("in loginSection1::process\n"); */
    if(_packet.type == wd::TASK_LOGIN_SECTION1){
        string username = _packet.msg;
        //此处要确保username末尾没有 \n
        if(username.back()=='\n'){
            username.pop_back();
        }
        /* printf("username:__%s__\n",username.c_str()); */
        string sql = "select * from login_info where name='" + username + "'";
        vector<vector<string>> ret =  _tcpconn->mysql_readQuery(sql);
        /* printf("ret.size after readQuery : %ld\n",ret.size()); */
        if(ret.size() == 1){
            printf("username not exist\n");
            wd::TLV tlv;
            tlv.type = wd::TASK_LOGIN_SECTION1_RESP_ERROR;
            tlv.length = 0;
            _tcpconn->sendInLoop(tlv);
            return;
        }
        /* printf("username exist\n"); */
        //用户名验证成功，将setting(含盐值)发给用户
        string setting = ret[1][2];
        string crypt = ret[1][3];
        //将用户信息放入UserManager单例

        shared_ptr<User> puser(new User);
        puser->set_username(username);
        puser->set_salt(setting);
        puser->set_crypt(setting);
        puser->set_camera_id(0);
        UserManger* user_m = UserManger::getInstance();
        user_m->add_user_info(_tcpconn,puser);
        
        _tcpconn->set_pwdp(crypt); //以便密码验证时可以取出 
        //构造TLV，将setting发给用户
        wd::TLV tlv;
        memset(&tlv,0,sizeof(tlv));
        tlv.type = wd::TASK_LOGIN_SECTION1_RESP_OK;
        tlv.length = setting.size();
        strncpy(tlv.data,setting.c_str(),tlv.length);
        _tcpconn->sendInLoop(tlv);
    }
}

void UserLoginSection1::get_setting(string & setting, char * passwd){
    int i,j;
    for(i=0, j=0; passwd[i] && j!= 4; ++i){
        if(passwd[i] == '$'){
            ++j;
        }
    }
    char buff[128] = {0};
    strncpy(buff,passwd,i-1);
    setting.assign(buff,i);

}


UserLoginSection2::UserLoginSection2(wd::Packet & packet, wd::TcpConnectionptr tcpconn)
    :_packet(packet)
     ,_tcpconn(tcpconn){

     }

void UserLoginSection2::process(){
    /* printf("in loginSection2::process\n"); */
    if(_packet.type == wd::TASK_LOGIN_SECTION2){
        string encoded = _packet.msg; //用户发来的密文
        /* printf("recv crypt from user:%s\n",encoded.c_str()); */
        string true_secret = _tcpconn->get_pwdp();
        /* printf("true_secret:%s\n",true_secret.c_str()); */
        if(encoded == true_secret){
            //验证成功
            LOG_DEBUG("log success!");
            wd::TLV tlv;
            memset(&tlv,0,sizeof(tlv));
            tlv.type = wd::TASK_LOGIN_SECTION2_RESP_OK;
            tlv.length = 0;
            _tcpconn->sendInLoop(tlv);
        }else{
            LOG_DEBUG("log fail!");
            wd::TLV tlv;
            memset(&tlv,0,sizeof(tlv));
            tlv.type = wd::TASK_LOGIN_SECTION2_RESP_ERROR;
            tlv.length = 0;
            _tcpconn->sendInLoop(tlv);
        }
    }

}

UserRegisterSection1::UserRegisterSection1(wd::Packet & packet, wd::TcpConnectionptr tcpconn)
    :_packet(packet)
     ,_tcpconn(tcpconn){

     }

void UserRegisterSection1::process(){
    /* printf("in register section1 \n"); */
    if(_packet.type == TASK_REGISTER_SECTION1 && _packet.length > 0){
        //确保名字未重复
        string username = _packet.msg;
        /* cout << "register name :"<<username<< endl; */
        string sql = "select * from login_info where name='"+username+"'";
        vector<vector<string>> ret = _tcpconn->mysql_readQuery(sql);
        /* printf("ret.size() = %ld\n",ret.size()); */
        if(ret.size() > 1){
            printf("注册的用户名重复了\n");
            wd::TLV tlv;
            memset(&tlv,0,sizeof(tlv));
            tlv.type = TASK_REGISTER_SECTION1_RESP_ERROR;
            tlv.length = 0;
            _tcpconn->sendInLoop(tlv);
            return;
        }
        //程序运行至此，说明用户名未重复，给用户回复一个盐值
        /* char * salt = GenRandomSring(_packet.length); */
        char * salt = GenRandomSring(_packet.length);
        printf("用户名未重复，生成盐值：%s\n",salt);
        //先暂存用户名和密码，待第二阶段密文获取后一起放入数据库
        _tcpconn->set_username(username);
        _tcpconn->set_salt(salt);

        wd::TLV tlv;
        memset(&tlv,0,sizeof(tlv));
        tlv.type = TASK_REGISTER_SECTION1_RESP_OK;
        tlv.length = strlen(salt);
        strncpy(tlv.data, salt, tlv.length);
        _tcpconn->sendInLoop(tlv);
    }
}


//生成盐值
char * UserRegisterSection1::GenRandomSring(int length){
    int flag, i;
    char* string;
    srand((unsigned) time(NULL ));
    if ((string = (char*) malloc(length)) == NULL )  {
        printf("malloc failed!flag:14\n");
        return NULL ;
    }
    for (i = 0; i < length+1; i++)  {
        flag = rand() % 3;
        switch (flag)  {
        case 0:  string[i] = 'A' + rand() % 26;  break;
        case 1:  string[i] = 'a' + rand() % 26;  break;
        case 2:  string[i] = '0' + rand() % 10;  break;
        default:  string[i] = 'x';  break;
        }
    }
    string[length] = '\0';
    return string;
}



UserRegisterSection2::UserRegisterSection2(wd::Packet & packet, wd::TcpConnectionptr tcpconn)
    :_packet(packet)
     ,_tcpconn(tcpconn){

     }

void UserRegisterSection2::process(){
    printf("in register section2 \n");
    if(_packet.type == TASK_REGISTER_SECTION2){
        string encoded = _packet.msg;
        if(is_crypt_valid(encoded.data()) == false){
            printf("无效密码\n");
            wd::TLV tlv;
            memset(&tlv,0,sizeof(tlv));
            tlv.type = TASK_REGISTER_SECTION2_RESP_ERROR;
            tlv.length = 0;
            _tcpconn->sendInLoop(tlv);
            return;
        }
        //密码无误则插入数据库，并给用户回复
        string username = _tcpconn->get_username();
        string salt = _tcpconn->get_salt();
        cout << "username:" << username <<
            " ,salt:" << salt <<
            " ,encoded:" << encoded << endl; 
        string sql = "insert into login_info(name,setting,encrypt) values('"
            + username + "','" + salt + "','" + encoded + "')"; 
        //cout << "sql:"<<  sql<< endl; 
        bool ret = _tcpconn->mysql_writeQuery(sql);
        if(ret == true){
            wd::TLV tlv;
            memset(&tlv,0,sizeof(tlv));
            tlv.type = TASK_REGISTER_SECTION2_RESP_OK;
            tlv.length = 0;
            _tcpconn->sendInLoop(tlv);

        }else{
            wd::TLV tlv;
            memset(&tlv,0,sizeof(tlv));
            tlv.type = TASK_REGISTER_SECTION2_RESP_ERROR;
            tlv.length = 0;
            _tcpconn->sendInLoop(tlv);
        }
    }
}




void UserRegisterSection2::get_setting(string & setting, char * passwd){
    int i,j;
    for(i=0, j=0; passwd[i] && j!= 4; ++i){
        if(passwd[i] == '$'){
            ++j;
        }
    }
    char buff[128] = {0};
    strncpy(buff,passwd,i-1);
    setting.assign(buff,i);

}
bool UserRegisterSection2::is_crypt_valid(const char * passwd){
    printf("check crypt...\n");
    if (passwd == NULL) {
        return false;  // 内存分配失败或严重错误
    }
    if (passwd[0] == '*') {
        return false;  // 返回 *0、*1 等错误标识
    }                                                                
    // 额外检查：哈希是否包含有效的加密算法标识（如 $6$）
    if (strlen(passwd) < 3 || passwd[0] != '$' || passwd[2] != '$') {
        return false;  // 盐值格式无效
    }
    return true;
}

}
